package main

import "fmt"

//切片slice 是数组的引用，因此切片也是引用类型
//声明切片类型
var a []int    //声明一个int类型切片
var b []string //声明一个字符型切片
func main() {
	fmt.Println(a)
	fmt.Println(b)
	c := []int{1, 2, 4}       //声明一个整型数组并初始化
	d := []string{"北京", "广州"} //声明一个字符型数组并初始化
	fmt.Println(a == nil)     //nil是为空的意思，如果数组为空，则为true，反之为false
	fmt.Println(b == nil)
	fmt.Println(c == nil)
	fmt.Println(d == nil)
	//长度和容量;容量是指底层数组的容量
	fmt.Printf("len(c):%d cap(c):%d\n", len(c), cap(c))
	fmt.Printf("len(d):%d cap(d):%d\n", len(d), cap(d))
	//1、从数组得到切片
	e := [...]int{1, 2, 3, 4, 5, 6, 7}
	f := e[0:4] //基于数组切割,左闭右开区间规则
	g := e[:4]  //-->[0:4]
	h := e[5:]  //-->[3:len(e)]
	fmt.Println(f)
	fmt.Printf("len(f):%d cap(f):%d\n", len(f), cap(f)) //容量是指底层数组的容量,底层数组从切片的第一个元素到最后一个元素的数量为容量
	fmt.Println(g)
	fmt.Println(h)
	fmt.Printf("len(h):%d cap(h):%d\n", len(h), cap(h))
	//	证明数组是值类型，切片是引用类型
	//	1.定义数组: 值类型 （深拷贝:拷贝的是数据本身 值类型的数据默认是深拷贝的类型有:array、int、float、string、bool、struct）
	a1 := [4]int{1, 2, 3, 4}
	//将a1的值赋值给a2
	a2 := a1
	//打印a1，a2
	fmt.Println(a1, a2)
	//修改a1的第一个元素的值
	a1[0] = 6
	//再次打印a1，a2，发现，a1的值因修改而改变，而a2不变
	fmt.Println(a1, a2)
	//	2.定义切片: 引用类型（浅拷贝:拷贝的是数据地址，多个变量指向同一块内存地址，引用类型的数据默认是浅拷贝:slice 、map、chan）
	b1 := []int{1, 2, 3, 4}
	//将b1的内存地址赋值给b2，因此，b2保存的是b1的内存地址
	b2 := b1
	//打印b1，b2的值，打印b2的值时会获取到b1的内存地址，且b1的内存地址保存的是b1的值
	fmt.Println(b1, b2)
	//修改b1的第一个元素的值
	b1[0] = 9
	//再次打印b1，b2，发现b2的值跟b1的值一样发生了改变，因为，b2保存的是b1的内存地址，打印b2的值时会获取到b1的内存地址，且b1的内存地址保存的是b1的值
	fmt.Println(b1, b2)
	fmt.Printf("%p\n", b1) //存储的值的地址
	fmt.Printf("%p\n", b2)
	fmt.Printf("%p\n", &b1) //自身的内存地址
	fmt.Printf("%p\n", &b2)
	var h8 = [...]int{1, 2, 3, 4, 5, 6}
	h1 := h8[0:3]
	h2 := h8[2:5]
	h3 := h8[3:5]
	h4 := h2[3:4]
	fmt.Printf("h1的长度为%d,容量为%d\n", len(h1), cap(h1))
	fmt.Printf("h2的长度为%d,容量为%d\n", len(h2), cap(h2))
	fmt.Printf("h3的长度为%d,容量为%d\n", len(h3), cap(h3))
	fmt.Printf("h4的长度为%d,容量为%d\n", len(h4), cap(h4))
}
